﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using AutoMapper;
using Elasticsearch.Synchronize.Domain.Aggregates.SynchronizeAggregate;
using Elasticsearch.Synchronize.Domain.Interface;
using Elasticsearch.Synchronize.Repository.Interface;
using Elasticsearch.Synchronize.Repository.MongoDbDTO;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Core.Operations;

namespace Elasticsearch.Synchronize.Repository.Repository
{
    public class SynchronizeItemRepository : ISynchronizeItemRepository
    {
        private readonly IMongoDbContext _context;

        public SynchronizeItemRepository(IMongoDbContext context)
        {
            _context = context;
        }

        public List<SynchronizeItem> GetItemsByRuleId(string ruleId)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(t => t.RuleId, ruleId);
            var result = _context.SynchronizeItem.FindSync(filter).ToList();
            return Mapper.Map<List<SynchronizeItemDTO>, List<SynchronizeItem>>(result);
        }

        public List<SynchronizeItem> GetItemsByRuleIdAndFilter(string ruleId, string jsonFilter)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(t => t.RuleId, ruleId);
            filter = filter & Builders<SynchronizeItemDTO>.Filter.Eq(t => t.JsonFilter, jsonFilter);
            var result = _context.SynchronizeItem.FindSync(filter).ToList();
            return Mapper.Map<List<SynchronizeItemDTO>, List<SynchronizeItem>>(result);
        }

        public void Add(SynchronizeItem item)
        {
            var dto = Mapper.Map<SynchronizeItem, SynchronizeItemDTO>(item);
            _context.SynchronizeItem.InsertOne(dto);
        }

        public void Delete(string identity)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(t => t.ItemId, identity);
            _context.SynchronizeItem.DeleteOne(filter);
        }

        public List<SynchronizeItem> GetValidItems()
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(t => t.Enabled, true);
            var result = _context.SynchronizeItem.FindSync(filter).ToList();
            return Mapper.Map<List<SynchronizeItemDTO>, List<SynchronizeItem>>(result);
        }

        public List<SynchronizeItem> GetIdleAndEnabledItems()
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(t => t.State, 0);
            filter = filter & Builders<SynchronizeItemDTO>.Filter.Eq(t => t.Enabled, true);
            var result = _context.SynchronizeItem.FindSync(filter).ToList();
            return Mapper.Map<List<SynchronizeItemDTO>, List<SynchronizeItem>>(result);
        }

        public void Update(string identity, SynchronizeItem item)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(f => f.ItemId, identity);
            var existedItem = _context.SynchronizeItem.Find(filter).FirstOrDefault();

            existedItem.State = (int)item.State;

            var update = Builders<SynchronizeItemDTO>.Update
                .Set(t => t.Threshold, existedItem.Threshold)
                .Set(t => t.Enabled, item.Enabled)
                .Set(t => t.State, existedItem.State);

            var updateResult = _context.SynchronizeItem.UpdateOne(filter, update);
        }

        public void BatchEnable(string ruleId)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(f => f.RuleId, ruleId);
            var update = Builders<SynchronizeItemDTO>.Update.Set(t => t.Enabled, true);
            var updateResult = _context.SynchronizeItem.UpdateMany(filter, update);
        }

        public void BatchDisable(string ruleId)
        {
            var filter = Builders<SynchronizeItemDTO>.Filter.Eq(f => f.RuleId, ruleId);
            var update = Builders<SynchronizeItemDTO>.Update.Set(t => t.Enabled, false);
            var updateResult = _context.SynchronizeItem.UpdateMany(filter, update);
        }
    }
}